#include "socketaddress.h"
#include "socket.h"
#include "format.h"
#include <iostream>
#include <vector>
#include <string>
#include <stdlib.h>
#include "threadpool.h"
#include "mutex.h"

using namespace std;

int sendnum = 0;
static Mutex mutex;

class TestSend :public Runnable
{
public:
    TestSend(int conn_num,int sendlen)
        :m_connnum(conn_num)
         ,m_sendlen(sendlen)
    {}

    virtual void run()
    {
        // set-up a server socket
        SocketAddress addr("127.0.0.1",7000);
        vector<Socket*> sockets;
        int num = 0;
        timeval val;
        val.tv_sec = 1;
        val.tv_usec = 0;
        string text(m_sendlen,'a');
        while( num++ < 100 )
        {
            int realconn = 0;
            for(; realconn < m_connnum; realconn++)
            {
                Socket* pSocket = new Socket();
                if (pSocket->connect(addr) != 0 || pSocket->sockfd() < 0)
                {
                    cout<<"connect failed,realconn ="<<realconn<<endl;
                    break;
                }
                else
                {
                    pSocket->setRecvTimeout(val);
                    pSocket->setSendTimeout(val);
                    sockets.push_back(pSocket);
                }
            }

            //cout<<"conn_count:"<<realconn<<endl;
            if (realconn == 0)
                break;

            char buf[4096] = {0};
            int len = 0;
            int bufsize = sizeof(buf);
            for(int i = 0; i < realconn; i++)
            {
                int sendbyte = sockets[i]->sendBytes(text.c_str(),text.size());
                if (sendbyte < 0)
                {
                    cout<<"send error"<<endl;
                    continue;
                }
                
                
                while( sockets[i] != NULL 
                        && (len = sockets[i]->recvBytes(buf,bufsize)) > 0)
                {
                    if ( len < sizeof(buf))
                        break;
                }
            }
            
            for (int i = 0 ; i < realconn; i++)
            {
                if (sockets[i]->sockfd() != -1)
                    sockets[i]->close();
            }
            
            ScopedMutex lock(&mutex);
            sendnum += realconn;

            sockets.clear();
        }
    }
private:
    int     m_connnum;
    int     m_sendlen;
};

int main(int argc, char** argv)
{
    if (argc < 3)
    {
        cout<<"usage:./client connect_count sendlen"<<endl;
        return 0;
    }
    
    int conn_count = atoi(argv[1]);
    int sendlen = atoi(argv[2]);

    if (conn_count < 1 || sendlen < 1)
    {
        cout<<"invalid run param"<<endl;
        return 0;
    }

    ThreadPool pool;
    vector<TestSend*> vTask;
    int thread_count = 16;
    for (int i = 0; i < thread_count; ++i)
    {
        TestSend* tmp = new TestSend(conn_count,sendlen);
        vTask.push_back(tmp);
        while(!pool.start(*tmp))
        {
            cout<<"starting task:"<<i<<endl;
            continue;
        }
    }
    int working = 1;
    while(working != 0)
    {
        // working == 16
        working = pool.working();
        {
            ScopedMutex lock(&mutex);
            cout<<"send:"<<sendnum<<endl;
            sendnum = 0;
        }
        Thread::sleep(1000);
    }
    
    for (vector<TestSend*>::iterator it = vTask.begin(); it != vTask.end(); ++it)
    {
        delete *it;
    }

    vTask.clear();
    
    return 0;
}
    


    
    
    
    
    
    
    
    
    
    
    
    
